package com.ironman.sailboat.mobile.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

public class FixedSizeLinkedBlockingDeque<T> {

    private final LinkedBlockingDeque<T> deque = new LinkedBlockingDeque<>();

    private final int dequeSize;

    public FixedSizeLinkedBlockingDeque(int dequeSize) {
        this.dequeSize = dequeSize;
    }

    public int size() {
        return deque.size();
    }

    public void offerLast(T data) {
        boolean offered = deque.offerLast(data);
        if (offered && deque.size() == dequeSize + 1) {
            deque.pollFirst();
        }
    }

    public void offerFirst(T data) {
        boolean offered = deque.offerFirst(data);
        if (offered && deque.size() == dequeSize + 1) {
            deque.pollLast();
        }
    }

    public List<T> subList(int size, boolean window) {
        if (window && deque.size() < size) {
            return null;
        }
        List<T> res = new ArrayList<>();
        int minSize = Math.min(deque.size(), size);
        for (int i = 0; i < minSize; i++) {
            res.add(deque.pollLast());
        }
        Collections.reverse(res);
        for (T t : res) {
            deque.offerLast(t);
        }
        return res;
    }

    public List<T> all() {
        return new ArrayList<>(deque);
    }

    public void clear() {
        deque.clear();
    }

    public static void main(String[] args) throws InterruptedException {
        FixedSizeLinkedBlockingDeque<Integer> windLinkedBlockingDeque = new FixedSizeLinkedBlockingDeque<>(10);
        for (int i = 0; i < 2000; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            windLinkedBlockingDeque.offerLast(i);

            System.out.println("all:" + windLinkedBlockingDeque.all());
            System.out.println("size:" + windLinkedBlockingDeque.size());
            System.out.println("window data:" + windLinkedBlockingDeque.subList(3, true));
        }
    }

}
